<?php
namespace app\common\library;

class CommandExecutor
{
    /**
     * 操作系统类型
     * @var string
     */
    private $osType;
    
    /**
     * 最后执行的命令
     * @var string
     */
    private $lastCommand;
    
    /**
     * 系统编码
     * @var string
     */
    private $systemEncoding;
    
    /**
     * 构造函数
     */
    public function __construct()
    {
        $this->osType = PHP_OS_FAMILY;
        // Windows系统默认使用GBK编码
        $this->systemEncoding = ($this->osType === 'Windows') ? 'GBK' : 'UTF-8';
    }
    
    /**
     * 执行Linux命令
     * @param string $command 要执行的命令
     * @return array ['code' => int, 'output' => string, 'error' => string]
     */
    public function executeLinux(string $command): array
    {
        if ($this->osType !== 'Linux') {
            return ['code' => -1, 'output' => '', 'error' => '当前系统不是Linux'];
        }
        
        $this->lastCommand = $command;
        $output = [];
        $returnCode = 0;
        
        exec($command . " 2>&1", $output, $returnCode);
        
        // 确保输出为UTF-8编码
        $output = array_map(function($line) {
            return $this->convertToUtf8($line);
        }, $output);
        
        return [
            'code' => $returnCode,
            'output' => implode("\n", $output),
            'error' => ($returnCode !== 0) ? '命令执行失败' : ''
        ];
    }
    
    /**
     * 执行Windows CMD命令
     * @param string $command 要执行的命令
     * @return array ['code' => int, 'output' => string, 'error' => string]
     */
    public function executeCmd(string $command): array
    {
        if ($this->osType !== 'Windows') {
            return ['code' => -1, 'output' => '', 'error' => '当前系统不是Windows'];
        }
        
        // 添加输出编码转换命令
        $this->lastCommand = "chcp 65001 > nul && cmd /c " . $command;
        $output = [];
        $returnCode = 0;
        
        exec($this->lastCommand . " 2>&1", $output, $returnCode);
        
        // 确保输出为UTF-8编码
        $output = array_map(function($line) {
            return $this->convertToUtf8($line);
        }, $output);
        
        return [
            'code' => $returnCode,
            'output' => implode("\n", $output),
            'error' => ($returnCode !== 0) ? '命令执行失败' : ''
        ];
    }
    
    /**
     * 执行PowerShell命令
     * @param string $command 要执行的命令
     * @return array ['code' => int, 'output' => string, 'error' => string]
     */
    public function executePowerShell(string $command): array
    {
        if ($this->osType !== 'Windows') {
            return ['code' => -1, 'output' => '', 'error' => '当前系统不是Windows'];
        }
        
        // 设置PowerShell输出编码为UTF-8
        $encodingCommand = '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; ';
        $this->lastCommand = "powershell -Command \"" . $encodingCommand . $command . "\"";
        $output = [];
        $returnCode = 0;

        // 设置Python输出编码为UTF-8
        putenv('PYTHONIOENCODING=utf8');
        putenv('LANG=en_US.UTF-8');
        
        exec($this->lastCommand . " 2>&1", $output, $returnCode);
        
        // 确保输出为UTF-8编码
        $output = array_map(function($line) {
            return $this->convertToUtf8($line);
        }, $output);
        
        return [
            'code' => $returnCode,
            'output' => implode("\n", $output),
            'error' => ($returnCode !== 0) ? '命令执行失败' : ''
        ];
    }
    
    /**
     * 获取最后执行的命令
     * @return string
     */
    public function getLastCommand(): string
    {
        return $this->lastCommand;
    }
    
    /**
     * 安全执行命令（过滤危险字符）
     * @param string $command 要执行的命令
     * @return string 过滤后的命令
     */
    public function sanitizeCommand(string $command): string
    {
        // 过滤一些危险字符
        $dangerous = ['|', '&', ';', '`', '$(', '>', '<'];
        return str_replace($dangerous, '', $command);
    }
    
    /**
     * 将字符串转换为UTF-8编码
     * @param string $string 要转换的字符串
     * @return string
     */
    private function convertToUtf8(string $string): string
    {
        // 检测字符串编码
        $encoding = mb_detect_encoding($string, ['ASCII', 'UTF-8', 'GBK', 'GB2312', 'BIG5'], true);
        
        // 如果检测失败，使用系统默认编码
        if (!$encoding) {
            $encoding = $this->systemEncoding;
        }
        
        // 如果不是UTF-8，则转换为UTF-8
        if ($encoding !== 'UTF-8') {
            $string = mb_convert_encoding($string, 'UTF-8', $encoding);
        }
        
        // 移除BOM标记
        $string = str_replace("\xEF\xBB\xBF", '', $string);
        
        return $string;
    }
    
    /**
     * 设置系统编码
     * @param string $encoding 编码方式
     * @return void
     */
    public function setSystemEncoding(string $encoding): void
    {
        $this->systemEncoding = $encoding;
    }
    
    /**
     * 执行普通命令
     * @param string $command
     * @return array
     */
    public function executeCommand(string $command): array
    {
        $output = [];
        $code = 0;
        
        // Windows系统添加编码转换命令
        if ($this->osType === 'Windows') {
            $command = "chcp 65001 > nul && " . $command;
        }
        
        // 设置环境变量
        putenv('PYTHONIOENCODING=utf8');
        putenv('LANG=en_US.UTF-8');
        
        exec($command . " 2>&1", $output, $code);
        
        // 确保输出为UTF-8编码
        $output = array_map(function($line) {
            return $this->convertToUtf8($line);
        }, $output);
        
        return [
            'code' => $code,
            'output' => implode("\n", $output),
            'error' => $code !== 0 ? '命令执行失败' : ''
        ];
    }
}